package Pow

/**
 * @author: 清秋
 * @email: 15770670622
 * @datetime: 13:51 2022/3/16
 * @Description:
 */
import (
	"bytes"
	"fmt"
	"ChainCodeProject/transaction"
	"ChainCodeProject/tools"
	"math/big"
	"strconv"
)

const BITS = 5 //目标值前面有多少个0

type ProofOfWork struct {
	//Block *block.Block //给谁工作的区块
	//TimeStamp int64
	//PrevHash []byte
	//Data []byte
	Block  BlockInterface
	Target *big.Int //要判断的系统给定的hash
}

type BlockInterface interface {
	GetTimeStamp() int64
	GetPrevHash() []byte
	GetData() []transaction.Transaction
}

/**
创建一个pow的实例，并且返回
*/
func NewPow(Block BlockInterface) *ProofOfWork {

	//var a int = 1
	target := big.NewInt(1) // 1
	target = target.Lsh(target, 255-BITS)
	pow := ProofOfWork{
		Block:  Block,
		Target: target,
	}
	return &pow
}

/**
寻找满足条件的随机数的
*/
func (pow *ProofOfWork) Run() (int64, []byte) {
	var nonce int64
	nonce = 0
	//先得到区块的hash
	block := pow.Block
	timeByte := []byte(strconv.FormatInt(block.GetTimeStamp(), 10))

	num := big.NewInt(0)
	//统一类型 []byte -> 转成 大整数类型
	for {
		nonceByte := []byte(strconv.FormatInt(nonce, 10))
		txsBytes := []byte{}
		//把block.GetData()的类型转换成[]byte
		for _, value := range block.GetData() {
			_, txBytes := value.Serialize()
			txsBytes = append(txsBytes, txBytes...)
		}
		hashByte := bytes.Join([][]byte{txsBytes, block.GetPrevHash(), nonceByte, timeByte}, []byte{})
		hash := tools.GetHash(hashByte)
		fmt.Println("正在寻找nonce，当前的nonce为", nonce)
		num = num.SetBytes(hash)
		if num.Cmp(pow.Target) == -1 {
			return nonce, hash
		}
		nonce++
	}
	return 0, nil
	/*
		if(a< target){

		}
	*/

}
